package com.example.myweb.Service.Auth.Impl;


import com.example.myweb.Domain.Entity.*;
import com.example.myweb.Dto.PollOptionResultDTO;
import com.example.myweb.Dto.PollResultDTO;
import com.example.myweb.Exception.CustomException;
import com.example.myweb.Repository.JpaRepository.AttachmentRepository;
import com.example.myweb.Repository.JpaRepository.PollVoteRepository;
import com.example.myweb.Service.Auth.PollService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class PollServiceImpl implements PollService {

    @Autowired
    private AttachmentRepository attachmentRepository;
    @Autowired
    private PollVoteRepository pollVoteRepository;
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    @Transactional
    public void vote(Long pollId, int optionIndex, User currentUser) {
        // 1. 查找投票附件是否存在且类型正确
        Attachment pollAttachment = attachmentRepository.findById(pollId)
                .filter(att -> att.getType() == Attachment.AttachmentType.POLL)
                .orElseThrow(() -> new CustomException("投票不存在或已失效", HttpStatus.NOT_FOUND));

        // 2. 解析投票选项，检查用户选择的选项是否有效
        List<String> options = parsePollOptions(pollAttachment.getMetadata());
        if (optionIndex < 0 || optionIndex >= options.size()) {
            throw new CustomException("无效的投票选项", HttpStatus.BAD_REQUEST);
        }

        // 3. 检查用户是否已投过票 (利用数据库唯一约束，也可以先查询)
        Optional<PollVote> existingVote = pollAttachment.getVotes().stream()
                .filter(vote -> vote.getUser().getUserId().equals(currentUser.getUserId()))
                .findFirst();

        if (existingVote.isPresent()) {
            throw new CustomException("你已经投过票了", HttpStatus.CONFLICT); // 409 Conflict
        }

        // 4. 创建并保存投票记录
        PollVote newVote = new PollVote();
        newVote.setAttachment(pollAttachment);
        newVote.setUser(currentUser);
        newVote.setOptionIndex(optionIndex);

        pollVoteRepository.save(newVote);
    }

    // 在 PollServiceImpl.java 中
    @Override
    @Transactional(readOnly = true)
    public PollResultDTO getPollResults(Long pollId, User currentUser) {
        Attachment pollAttachment = attachmentRepository.findById(pollId)
                .orElseThrow(() -> new CustomException("投票不存在", HttpStatus.NOT_FOUND));

        // 1. 解析投票元数据
        String question;
        List<String> optionTexts;
        try {
            Map<String, Object> metadata = objectMapper.readValue(pollAttachment.getMetadata(), new TypeReference<>() {});
            question = (String) metadata.get("question");
            optionTexts = (List<String>) metadata.get("options");
        } catch (IOException e) {
            throw new IllegalStateException("无法解析投票数据");
        }

        // 2. 统计各选项票数
        List<Object[]> voteCountsRaw = pollVoteRepository.countVotesByOptionIndex(pollId);
        Map<Integer, Long> voteCountsMap = voteCountsRaw.stream()
                .collect(Collectors.toMap(
                        row -> (Integer) row[0],
                        row -> (Long) row[1]
                ));

        // 3. 组装选项结果列表
        long totalVotes = 0;
        List<PollOptionResultDTO> optionResults = new ArrayList<>();
        for (int i = 0; i < optionTexts.size(); i++) {
            long count = voteCountsMap.getOrDefault(i, 0L);
            optionResults.add(new PollOptionResultDTO(optionTexts.get(i), count));
            totalVotes += count;
        }

        // 4. 检查当前用户是否已投票
        Integer userVotedOptionIndex = null;
        if (currentUser != null) {
            userVotedOptionIndex = pollAttachment.getVotes().stream()
                    .filter(vote -> vote.getUser().getUserId().equals(currentUser.getUserId()))
                    .map(PollVote::getOptionIndex)
                    .findFirst()
                    .orElse(null);
        }

        // 5. 组装最终的DTO
        PollResultDTO resultDTO = new PollResultDTO();
        resultDTO.setPollId(pollId);
        resultDTO.setQuestion(question);
        resultDTO.setOptions(optionResults);
        resultDTO.setTotalVotes(totalVotes);
        resultDTO.setUserVotedOptionIndex(userVotedOptionIndex);

        return resultDTO;
    }

    // 辅助方法：从JSON metadata中解析出选项列表
    private List<String> parsePollOptions(String metadataJson) {
        try {
            Map<String, Object> metadata = objectMapper.readValue(metadataJson, new TypeReference<>() {});
            return (List<String>) metadata.get("options");
        } catch (IOException e) {
            // 在生产环境中应记录日志
            return List.of();
        }
    }
}